var myName = '真心鎮大冒險';
function callName () {
console.log(this, this.myName);
}
callName();
可以看到這是上一篇文章的範例,並且在這裡 callName();
就是典型的 簡易呼叫(Simple Call)。
並且要特別提醒!
盡可能不要使用 簡易呼叫(Simple Call) 的 this
。
原因呢我們後面會提到,我們先接著看下面的範例:
var myName = '真心鎮大冒險';
function callName () {
console.log(this, this.myName);
}
// IIFE
(function () {
console.log(this.myName);
function callSomeone () {
console.log(this.myName);
}
callSomeone();
})();
首先我們利用一個立即函式包住 console.log(this.myName);
這裡的這個 this.myName 因為沒有在立即函式的內部定義,所以會指向外層的 真心鎮大冒險。
然後我們在這個裡面又訂一個另外一個函式 callSomeone,並且立刻執行他。
所以在這裡呢,callSomeone();
也是一個典型的 簡易呼叫(Simple Call)。
所以這裡的 this
也是指向全域的 window 物件。
在這邊提醒大家~之前有提過一個概念就是
所謂的全域變數都是掛在 window 這個物件下,所以很多人會以為我們執行 簡易呼叫(Simple Call) 的時候,會是 window.callSomeone()
的感覺。
但其實並不是這樣的概念,下一篇文章會再詳細說明這個部分。
簡單來說重點就是
window.callSomeone()
的執行方式並不是 簡易呼叫(Simple Call)。this
指向的全域的物件 window。了解了這些以後我們繼續往下~
之前我們有討論到閉包的狀況,調用函式中回傳的函式,也是屬於 簡易呼叫(Simple Call) 的一種。
var myName = '真心鎮大冒險';
function easyCard (base) {
var money = base;
var name = '悠遊卡';
return function (update) {
money = money + update;
console.log(this.myName, money);
}
}
var MingEasyCard = easyCard(100);
MingEasyCard(10);
執行上述的程式碼,可以看到 this.myName
的指向還是全域的 '真心鎮大冒險'。
這邊就得證 MingEasyCard(10);
也是 屬於 簡易呼叫(Simple Call) 的一種。
再來討論 callBack 的狀況
callback就是將一個函式傳到另一個函式內,並且在另外一個函式內執行。
那麼,再另一個函式裡面執行的形式,也是屬於 簡易呼叫(Simple Call) 喔!
那麼一樣這邊的 this
指向的就是全域 window。
var myName = '真心鎮大冒險';
function myEasyCard (callback) {
var money = 100;
return callback(money);
}
myEasyCard(function (money) {
console.log(this.myName, money + 100);
});
所以結果印出來就會是 真心鎮大冒險 200
除了我們這邊寫的這個之外呢,還有就是 forEach 的例子
var myName = '真心鎮大冒險';
var a = [1, 2, 3];
a.forEach(function (i) {
console.log(this.myName, i);
});
這樣執行了以後呢,會得到下面的結果:
所以 callback function 也是屬於 簡易呼叫(Simple Call) 喔!
其 this 的指向會指向到 window 物件。
再來就是最後一個範例:
var myName = '真心鎮大冒險';
var family = {
myName: '小明家',
callName: function () {
setTimeout(function () {
console.log(this.myName);
}, 1000);
}
}
family.callName();
請問這樣console.log印出來會是 真心鎮大冒險 還是 小明家 呢?
答案如上,印出來是 真心鎮大冒險。
原因是因為,雖然執行的方式是在 family 下執行,的確callName裡面執行環境的指向是family的物件。
但是在那裏面又包了一個setTimeout的執行環境,傳入的是 callback function,所以 callback function 裡面的 this 指向就還是全域的 window物件。
所以答案就是 真心鎮大冒險喔!
但是,如果我今天就是要取得family這個物件裡面的 myName,也就是 小明家 的話,我該怎麼做呢?
很簡單,只需要先在 callName的執行環境中,把this保存再某一個變數裡面,並且替換 this => 變數名稱 就可以了喔!
程式碼如下:
var myName = '真心鎮大冒險';
var family = {
myName: '小明家',
callName: function () {
var self = this;
setTimeout(function () {
console.log(self.myName);
}, 1000);
}
}
family.callName();
這樣子執行的結果就會印出小明家了
其中乘載 this 的變數名稱通常會被叫做 self、vm、that等,依據不同的開發環境會有不同的命名習慣。
好~那麼這篇文章主要就是介紹 簡易呼叫(Simple Call),如果沒有問題的話,我們就繼續往下一篇文章邁進吧!